/**
   Project: primeval compiler
   File: CodeGenerator.h
   Authors: Sebastian Zanner Matr.Nr.: 0855172
   E-Mail: sebastian.zanner@stud.sbg.ac.at
*/

#ifndef CODEGENERATOR_H_INCLUDED
#define CODEGENERATOR_H_INCLUDED

#include <stdio.h>
#include <stdlib.h>
#include "SymbolTable.h"

// Format 1
#define ADDI 1
#define SUBI 2
#define MULI 3
#define DIVI 4
#define MODI 5
#define CMPI 6

#define LDW  7
#define STW  8

#define POP  9
#define PSH  10

#define BEQ  11
#define BGE  12
#define BGT  13
#define BLE  14
#define BLT  15
#define BNE  16

#define BR   17
#define BSR  18

#define READI  19
#define PRINTI 20
#define READC 21
#define PRINTC 22
#define READB 23
#define PRINTB 24
#define PRINTS 25

// Format 2
#define ADD 26
#define SUB 27
#define MUL 28
#define Div 29
#define Mod 30
#define CMP 31
#define RET 32

// Format 3
#define JSR 33

#define MAXCODE 1000
#define NOOFREG 32

#define PC          0
#define HEAPSTART   512 * 4
#define GPSTART     256 * 4

#define LINK        31
#define SP          30
#define FP          29
#define RETREG      28

#define HEAPREG     27
#define GP          26

#define MODECONST 1
#define MODEVAR   2
#define MODEREG   3
#define MODEREF   4
#define MODECOND  5

struct item
{
    int mode;
    type_t type;
    int reg;    //address = reg + offset
    int offset;
    int value; //if we are in constant mode

    // ifStatement
    int op;
    int fls;
    int tru;
};

typedef struct item ptr item_t;

struct CodeLine
{
    int op;
    int one;
    int two;
    int three;
};

typedef struct CodeLine ptr codeline_t;
typedef codeline_t ptr code_t;
typedef int ptr registers_t;

int             programCounter;
code_t          code;
registers_t     registers;
int             GPOffset;
int             SPOffset;
int             ParamOffset;
int             registersUsed;
int             heapInitCodePos;

void initCodeGenerator();
item_t getVarItem(object_t o);
item_t getConstItem(int value);
void arithBinaryOperator(int operator, item_t left, item_t right);
void assignBinaryOperator(item_t left, item_t right);
void load(item_t item);
void put(int op, int one, int two, int three);
void putSpecific(int line, int op, int one, int two, int three);
void printCodeLine(codeline_t codeline);
void load(item_t item);
void refToReg(item_t item);
void varToReg(item_t item);
void constToReg(item_t item);
void addObjectToMonster(object_t o);
void field(object_t object, item_t item);
void indexer(item_t indexItem, item_t item);
item_t mallocItem(type_t type, item_t sizeItem);
void setParamAddresses(object_t procedure);

int isIOProcedure(string_t name);
int putOutput(string_t name, item_t item);
int putInput(string_t name, item_t item);

string_t getInstruction(int key);
void freeReg(int reg);
int getRegister();
void printItem(item_t item);
void run();
void incr(int pointer);
void incrHeap(int size, item_t sizeItem);


// ifStatement
void expressionOperator(item_t left, item_t right, int operator);
void factorOperator(item_t item);
int forwardJump();
void conditionalJump(item_t item);
int negateBranch(int op);
void fixUp(int branchAddress);
void fixLink(int branchAddress);

//while statement
void bJump(int backAddress);

//boolean expressions
void loadBool(item_t item);
void unloadBool(item_t item);
int concatenate(int one, int two);
void simpleExpressionOR(item_t item);
void simpleExpressionAND(item_t item);
int branch(int or_and, int op);
item_t getConstBoolItem(string_t value);
item_t getConstCharItem(string_t value);

int branchAddress;
int fJumpAddress;
int bJumpAddress;
int returnFJumpAddress;

void encode(unsigned long *result, int op, char a, char b, int c);
int decode(unsigned long *instruction, char *op, char *a, char *b, int *c);

void prologue();
void epilogue(int paramSize);
int fJumpChain(int branchAddress);
void addObjectToParams(object_t procedure, object_t param);
void pushParameter(item_t item);
void pushUsedRegisters();
void popUsedRegisters();
int isBSR(int address);
int sJump(int branchAddress);

void negateItem(item_t item);

#endif // CODEGENERATOR_H_INCLUDED
